# include "openAdressingHashMap.h"

OpenAdressingHashMap * newOpenAdressingHashMap(int size,  ProbingType type) {
   OpenAdressingHashMap *new = (OpenAdressingHashMap *) malloc(sizeof(OpenAdressingHashMap));
   if (!new) logMessage("util.hashs","openAdresingHashMap","newOpenAdressingHashMap","Memória Insuficiente - HashMap",CRITICAL);
   new->type = type;
   new->list = (HashMapElem **) malloc(sizeof(HashMapElem *)*(size+1));
   new->size = size;
   if (!new->list) logMessage("util.hashs","openAdresingHashMap","newOpenAdressingHashMap","Memória Insuficiente - List",CRITICAL);
   return new;
}

static int increment (OpenAdressingHashMap *map, int i) {
   if (map->type == LINEAR) return (i+1)%map->size;
   else return (i*2)%map->size;
}

int putOpenAdressing (OpenAdressingHashMap *map, void *key, void *data) {
   int start,k = (map->hash)(key,map->size);
   int inserted = 0;
   start = k;
   if (!map) return 0;
   if (k >= map->size || k < 0) return 0;
   do {
      if (map->list[k] == NULL) {
         inserted = 1;
         map->list[k] = newHashMapElem(key,data);
         if (!map->list[k]) return 0;
      }
      else {
         if ((map->eq)(key,map->list[k]->key)) {
            inserted = 1;
            map->list[k]->data = data;
         }
         else k = increment(map,k);
      }
   } while (start != k && !inserted);
   if (inserted) return 1;
   else return 0;
}

void * getOpenAdressing (OpenAdressingHashMap *map, void *key) {
   int start,k = (map->hash)(key,map->size);
   int found = 0;
   if (!map) return NULL;
   if (k >= map->size || k < 0) return NULL;
   do {
      if (!map->list[k]) return NULL;
      else {
         if (map->list[k]&&((map->eq)(key,map->list[k]->key)))
            return map->list[k]->data;
         else k = increment(map,k);
      }
   } while (start != k);
   return NULL;
}

LinkedList * keySetOpenAdressing (OpenAdressingHashMap *map) {
	int i;
	LinkedList *list = NULL;
	for (i=0;i<map->size;i++) {
		if (map->list[i])
			list = insertElemHead(list,map->list[i]->key);
	}
	return list;
}
